home *** CD-ROM | disk | FTP | other *** search
- /*
- // Pi.cc -- pi$@%U%)!<%^%C%H2hA|$r07$&(J
- //
- // created in 3/21/1993
- // revised in 2/13/1994
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include "defs.h"
- #include "Pi.h"
- #include "Pic.h"
-
- static unsigned char ColorTable[16 + 1][16 + 1];
- static unsigned char *ColorTable256;
- static int PreviousColor;
- static int RestLength;
- static unsigned char *Screen2;
- static int PiMode;
- static int PiXRatio, PiYRatio;
- static int PiPlaneSize;
- static int (*ReadColor)();
- static void (*WriteColor)( int Previous, int Color );
-
- void ExpandPi();
- int PiReadLength();
- int PiReadColor16();
- int PiReadColor256();
- void CompressPi();
- void PiWriteLength( int n );
- void PiWriteColor16( int Previous, int Color );
- void PiWriteColor256( int Previous, int Color );
- int Search( unsigned char *s1, int offset );
- void ColorTableInitialize();
-
- void PiLoad()
- {
- int i, OldWidth, x, y;
- int Limit;
-
- if ( fp == NULL && (fp = fopen( File, "rb" )) == NULL )
- error ("%s: No such file");
- AllocateBuffer();
- BitBufferLength = 0;
- PicBitLoad (8);
- if ( PicWord != 'P' )
- error ("%s: Is not pi format");
- PicBitLoad (8);
- if ( PicWord != 'i' )
- error ("%s: Is not pi format");
- for ( i = 0; i < 16384; i++ ) {
- PicBitLoad (8);
- if ( PicWord == 0x1a )
- break;
- }
- if ( i == 16384 )
- error ("%s: Is not pi format");
- for ( i = 0; i < 16384; i++ ) {
- PicBitLoad (8);
- if ( PicWord == 0 )
- break;
- }
- if ( i == 16384 )
- error ("%s: Is not pi format");
- PicBitLoad (8);
- if ( (PiMode = PicWord) & ~0x80 )
- error ("%s: Unknown pi-mode");
- PicBitLoad (8);
- PiXRatio = PicWord;
- PicBitLoad (8);
- PiYRatio = PicWord;
- if ( PiXRatio == 0 || PiYRatio == 0 )
- PiXRatio = PiYRatio = 1;
- PicBitLoad (8);
- if ( (PiPlaneSize = PicWord) != 4 && PiPlaneSize != 8 )
- error ("%s: Irregal place size");
- if ( PiPlaneSize == 8 ) {
- if ( (ColorTable256 = (unsigned char*)malloc (65536 + 16)) == NULL )
- error ("%s: Insufficient memory");
- }
- else
- ColorTable256 = NULL;
- PicBitLoad (8);
- PicBitLoad (8);
- PicBitLoad (8);
- PicBitLoad (8);
- PicBitLoad (16);
- for ( i = PicWord; i > 0; i-- )
- PicBitLoad (8);
- PicBitLoad (16);
- Width = PicWord;
- PicBitLoad (16);
- Height = PicWord;
- if ( Screen != NULL )
- free (Screen);
- if ( (Screen = (int16*)malloc ((Size = Width * Height * PiXRatio * PiYRatio * 2) + 64)) == NULL )
- error ("%s: Insufficient memory");
- if ( (Screen2 = (unsigned char*)malloc (Width * (Height + 2) + 64)) == NULL )
- error ("%s: Insufficient memory");
- for ( i = 0; i < Width * (Height + 2); i++ )
- Screen2[i] = 0;
- if ( PiMode & 0x80 ) {
- if ( PiPlaneSize == 4 ) {
- for ( i = 0; i < 16; i++ ) {
- Red[i] = ((i & 2)? 1 : 0) * (1 + (i > 7)) * 16 - 1;
- Green[i] = ((i & 4)? 1 : 0) * (1 + (i > 7)) * 16 - 1;
- Blue[i] = ((i & 1)? 1 : 0) * (1 + (i > 7)) * 16 - 1;
- }
- }
- else {
- for ( i = 0; i < 256; i++ ) {
- Red[i] = ((i >> 2) & 7) << 2;
- Green[i] = (i >> 5) << 2;
- Blue[i] = (i & 3) << 3;
- }
- }
- }
- else {
- for ( i = 0; i < (1 << PiPlaneSize); i++ ) {
- PicBitLoad (8);
- Red[i] = PicWord >> 3;
- PicBitLoad (8);
- Green[i] = PicWord >> 3;
- PicBitLoad (8);
- Blue[i] = PicWord >> 3;
- }
- }
- for ( i = 0; i < 256; i++ )
- Palette[i] = (Red[i] << 5) | (Green[i] << 10) | Blue[i];
- ColorTableInitialize();
- ExpandPi();
- Limit = Width * (Height + 2);
- for ( i = Width * 2; i < Limit; i++ )
- Screen[i - Width * 2] = Palette[Screen2[i]];
- if ( PiXRatio != 1 || PiYRatio != 1 ) {
- OldWidth = Width;
- Width = Width * PiYRatio;
- Height = Height * PiXRatio;
- for ( y = Height - 1; y >= 0; y-- ) {
- for ( x = Width - 1; x >= 0; x-- ) {
- Screen[x + y * Width] = Screen[x / PiYRatio + (y / PiXRatio) * OldWidth];
- }
- }
- }
- if ( PiPlaneSize == 8 )
- free (ColorTable256);
- free (Screen2);
- free (BitBuffer);
- if ( fp != stdin )
- fclose (fp);
- if ( PiPlaneSize == 4 )
- MaxColorGuaranteed = 16;
- else
- MaxColorGuaranteed = 256;
- }
-
- void PiSave()
- {
- int i, j;
- int32 HalfSize, MaxColor;
-
- for ( i = 0; i < 16; i++ )
- Palette[i] = -1;
- MaxColor = 0;
- HalfSize = Size / 2;
- if ( (Screen2 = (unsigned char*)malloc (Width * (Height + 2) + 16)) == NULL )
- error ("%s: Insufficient memory");
- for ( i = 0; i < HalfSize; i++ ) {
- for ( j = 0; j < MaxColor; j++ )
- if ( Palette[j] == Screen[i] )
- break;
- Screen2[i + Width * 2] = j;
- if ( j == MaxColor ) {
- Palette[j] = Screen[i];
- MaxColor++;
- if ( MaxColor > 256 )
- error ("%s: Too many colors for pi format");
- }
- }
- MaxColorGuaranteed = MaxColor;
- if ( fp == NULL && (fp = fopen( File, "wb" )) == NULL )
- error ("%s: No such file");
- for ( i = 0; i < MaxColor; i++ ) {
- Red[i] = ((Palette[i] >> 5) & 31) << 3;
- Green[i] = (Palette[i] >> 10) << 3;
- Blue[i] = (Palette[i] & 31) << 3;
- }
- AllocateBufferForWriting();
- BitBufferLength = BitBufferSize;
- BitLength = 8;
- BitBufferPointer = BitBuffer;
- if ( MaxColor <= 16 ) {
- ColorTable256 = NULL;
- PiPlaneSize = 4;
- ColorTableInitialize();
- PicBitWrite( 8, 'P' ); /* id; */
- PicBitWrite( 8, 'i' );
- PicBitWrite( 8, 26 ); /* eof; */
- PicBitWrite( 8, 0 ); /* separator; */
- PicBitWrite( 8, 0 ); /* mode; */
- PicBitWrite( 8, 0 ); /* ratio; */
- PicBitWrite( 8, 0 ); /* ratio; */
- PicBitWrite( 8, 4 ); /* depth; */
- PicBitWrite( 8, '-' ); /* machine code; */
- PicBitWrite( 8, '-' ); /* machine code; */
- PicBitWrite( 8, '-' ); /* machine code; */
- PicBitWrite( 8, '-' ); /* machine code; */
- PicBitWrite( 16, 0 ); /* reserved size; */
- PicBitWrite( 16, Width );
- PicBitWrite( 16, Height );
- for ( i = 0; i < 16; i++ ) {
- PicBitWrite( 8, Red[i] );
- PicBitWrite( 8, Green[i] );
- PicBitWrite( 8, Blue[i] );
- }
- }
- else {
- if ( (ColorTable256 = (unsigned char*)malloc (65536 + 16)) == NULL )
- error ("%s: Insufficient memory");
- PiPlaneSize = 8;
- ColorTableInitialize();
- PicBitWrite( 8, 'P' ); /* id; */
- PicBitWrite( 8, 'i' );
- PicBitWrite( 8, 26 ); /* eof; */
- PicBitWrite( 8, 0 ); /* separator; */
- PicBitWrite( 8, 0 ); /* mode; */
- PicBitWrite( 8, 0 ); /* ratio; */
- PicBitWrite( 8, 0 ); /* ratio; */
- PicBitWrite( 8, 8 ); /* depth; */
- PicBitWrite( 8, '-' ); /* machine code; */
- PicBitWrite( 8, '-' ); /* machine code; */
- PicBitWrite( 8, '-' ); /* machine code; */
- PicBitWrite( 8, '-' ); /* machine code; */
- PicBitWrite( 16, 0 ); /* reserved size; */
- PicBitWrite( 16, Width );
- PicBitWrite( 16, Height );
- for ( i = 0; i < 256; i++ ) {
- PicBitWrite( 8, Red[i] );
- PicBitWrite( 8, Green[i] );
- PicBitWrite( 8, Blue[i] );
- }
- }
- CompressPi();
- PicBufferWriteFlush();
- if ( PiPlaneSize == 8 )
- free (ColorTable256);
- free (Screen2);
- free (BitBuffer);
- if ( fp != stdout )
- fclose (fp);
- }
-
- void ColorTableInitialize()
- {
- int i, j;
-
- if ( PiPlaneSize == 4 ) {
- for ( j = 0; j < 16; j++ )
- for ( i = 0; i < 16; i++ )
- ColorTable[j][i] = (16 - i + j) & 15;
- }
- else {
- for ( j = 0; j < 256; j++ )
- for ( i = 0; i < 256; i++ )
- ColorTable256[i + j * 256] = (256 - i + j);
- }
- }
-
- void ExpandPi()
- {
- int i;
- int c0, c1, c2, c3;
- unsigned char *Screen3, *p;
- int RestSize;
- int PreviousPosition, Position, Length;
-
- if ( PiPlaneSize == 4 )
- ReadColor = PiReadColor16;
- else
- ReadColor = PiReadColor256;
- PreviousColor = 0;
- c0 = ReadColor();
- c1 = ReadColor();
- Screen3 = Screen2;
- for ( i = 0; i < Width; i++ ) {
- *Screen3++ = c0;
- *Screen3++ = c1;
- }
- RestSize = Width * Height / 2;
- for ( PreviousPosition = -1;; ) {
- PicBitLoad (2);
- if ( (Position = PicWord) == 3 ) {
- PicBitLoad (1);
- Position += PicWord;
- }
- if ( PreviousPosition == Position ) {
- PreviousPosition = -1;
- PreviousColor = *(Screen3 - 1);
- for ( ;; ) {
- *Screen3++ = ReadColor();
- *Screen3++ = ReadColor();
- RestSize--;
- PicBitLoad (1);
- if ( PicWord == 0 )
- break;
- }
- continue;
- }
- PreviousPosition = Position;
- if ( (Length = PiReadLength()) <= 0 )
- continue;
- if ( (RestSize -= Length) < 0 ) {
- Length += RestSize;
- RestSize = 0;
- }
- #define MoveMem(Source,Destination,Size) {\
- unsigned char *s, *d;\
- int Rest;\
- s = Source;\
- d = Destination;\
- Rest = Size;\
- while ( --Rest >= 0 ) {\
- *d++ = *s++;\
- *d++ = *s++;\
- }\
- Destination = d; }
- switch (Position) {
- case 4:
- MoveMem( Screen3 - (Width + 1), Screen3, Length );
- break;
- case 3:
- MoveMem( Screen3 - (Width - 1), Screen3, Length );
- break;
- case 2:
- MoveMem( Screen3 - (Width * 2), Screen3, Length );
- break;
- case 1:
- MoveMem( Screen3 - Width, Screen3, Length );
- break;
- case 0:
- p = Screen3 - 4;
- c3 = *p++;
- c2 = *p++;
- c1 = *p++;
- c0 = *p++;
- Screen3 += Length + Length;
- if ( c0 == c1 ) {
- c2 = c0;
- c3 = c1;
- }
- if ( Length == 1) {
- *p++ = c3;
- *p++ = c2;
- }
- else {
- Length = (Length + 1) >> 1;
- do {
- int n;
- n = (Length > 16000) ? 16000 : Length;
- Length -= n;
- do {
- *p++ = c3;
- *p++ = c2;
- *p++ = c1;
- *p++ = c0;
- } while (--n > 0);
- } while (Length);
- }
- break;
- }
- if ( RestSize <= 0 )
- break;
- }
- }
-
- int PiReadLength()
- {
- int bits;
- int re;
-
- PicBitLoad (1);
- if ( PicWord == 0 )
- return 1;
- for ( bits = 1;; bits++ ) {
- PicBitLoad (1);
- if ( PicWord == 0 )
- break;
- }
- PicBitLoad (bits);
- re = PicWord + (1 << bits);
- return re;
- }
-
- int PiReadColor16()
- {
- int Color, k;
- unsigned char *p, *s, *d;
-
- PicBitLoad (1);
- if ( PicWord != 0 ) {
- PicBitLoad (1);
- Color = PicWord;
- goto Exit;
- }
- PicBitLoad (1);
- if ( PicWord == 0 ) {
- PicBitLoad (1);
- Color = PicWord + 2;
- goto Exit;
- }
- PicBitLoad (1);
- if ( PicWord == 0 ) {
- PicBitLoad (2);
- Color = PicWord + 4;
- goto Exit;
- }
- PicBitLoad (3);
- Color = PicWord + 8;
- Exit:
- p = ColorTable[PreviousColor];
- k = p[Color];
- if (Color) {
- s = p + Color;
- d = s + 1;
- while (Color--) *--d = *--s;
- *p = (unsigned char)k;
- }
- return PreviousColor = k;
- }
-
- int PiReadColor256()
- {
- int Color, k;
- unsigned char *s, *d, *p;
-
- PicBitLoad (1);
- if ( PicWord != 0 ) {
- PicBitLoad (1);
- Color = PicWord;
- goto Exit;
- }
- PicBitLoad (1);
- if ( PicWord == 0 ) {
- PicBitLoad (1);
- Color = PicWord + 2;
- goto Exit;
- }
- PicBitLoad (1);
- if ( PicWord == 0 ) {
- PicBitLoad (2);
- Color = PicWord + 4;
- goto Exit;
- }
- PicBitLoad (1);
- if ( PicWord == 0 ) {
- PicBitLoad (3);
- Color = PicWord + 8;
- goto Exit;
- }
- PicBitLoad (1);
- if ( PicWord == 0 ) {
- PicBitLoad (4);
- Color = PicWord + 16;
- goto Exit;
- }
- PicBitLoad (1);
- if ( PicWord == 0 ) {
- PicBitLoad (5);
- Color = PicWord + 32;
- goto Exit;
- }
- PicBitLoad (1);
- if ( PicWord == 0 ) {
- PicBitLoad (6);
- Color = PicWord + 64;
- goto Exit;
- }
- PicBitLoad (7);
- Color = PicWord + 128;
- Exit:
- p = ColorTable256 + PreviousColor * 256;
- k = p[Color];
- if (Color) {
- s = p + Color;
- d = s + 1;
- while (Color--) *--d = *--s;
- *p = k;
- }
- return PreviousColor = k;
- }
-
- void PiWriteColor16( int Previous, int Color )
- {
- int n, k, k0;
- unsigned char *p;
-
- p = ColorTable[Previous];
- n = 0;
- k = *p;
- while ( Color != k && n++ < 16 ) {
- k0 = *++p; *p = k; k = k0;
- }
- ColorTable[Previous][0] = Color;
- if ( n < 2 ) {
- PicBitWrite( 1, 1);
- PicBitWrite( 1, n );
- }
- else if ( n < 4 ) {
- PicBitWrite( 2, 0 );
- PicBitWrite( 1, n - 2 );
- }
- else if ( n < 8 ) {
- PicBitWrite( 3, 2 );
- PicBitWrite( 2, n - 4 );
- }
- else {
- PicBitWrite( 3, 3 );
- PicBitWrite( 3, n - 8 );
- }
- }
-
- void PiWriteColor256( int Previous, int Color )
- {
- int n, k, k0;
- unsigned char *p;
-
- p = ColorTable256 + Previous * 256;
- n = 0;
- k = *p;
- while ( Color != k && n++ < 256 ) {
- k0 = *++p; *p = k; k = k0;
- }
- *(ColorTable256 + Previous * 256) = Color;
- if ( n < 2 ) {
- PicBitWrite( 1, 1 );
- PicBitWrite( 1, n );
- }
- else if ( n < 4 ) {
- PicBitWrite( 2, 0 );
- PicBitWrite( 1, n - 2 );
- }
- else if ( n < 8 ) {
- PicBitWrite( 3, 2 );
- PicBitWrite( 2, n - 4 );
- }
- else if ( n < 16 ) {
- PicBitWrite( 4, 6 );
- PicBitWrite( 3, n - 8 );
- }
- else if ( n < 32 ) {
- PicBitWrite( 5, 14 );
- PicBitWrite( 4, n - 16 );
- }
- else if ( n < 64 ) {
- PicBitWrite( 6, 30 );
- PicBitWrite( 5, n - 32 );
- }
- else if ( n < 128 ) {
- PicBitWrite( 7, 62 );
- PicBitWrite( 6, n - 64 );
- }
- else {
- PicBitWrite( 7, 63 );
- PicBitWrite( 7, n - 128 );
- }
- }
-
- int Search( unsigned char *s1, int offset )
- {
- int m;
- int count;
-
- if (*s1 != s1[offset]) return 0;
- m = RestLength + RestLength;
- count = 30000;
- if ( count > m )
- count = m;
- m -= count;
- while ( *s1 == s1[offset] ) {
- if (!--count)
- break;
- s1++;
- }
- return RestLength - (m + count + 1) / 2;
- }
-
- inline void bitWriteTiny( int len, int data )
- {
- while ( len-- ) {
- PicBitWrite( 1, data >> len );
- }
- }
-
- void PiWriteLength( int n )
- {
- int len, b;
-
- len = 0;
- b = 2;
- while ( n > b - 1 ) {
- len++;
- b <<= 1;
- }
- bitWriteTiny( len + 1, 0xfffffffe );
- if ( len )
- bitWriteTiny(len, n - b / 2);
- }
-
- #define calc0(p) (((p)[Width2 - 2] == (p)[Width2 - 1]) \
- ? Search((p) + Width2 - 2, 2) \
- : Search((p) + Width2 - 4, 4))
- #define calc1(p) Search((p) + Width, Width)
- #define calc2(p) Search((p), Width2)
- #define calc3(p) Search((p) + Width + 1, Width - 1)
- #define calc4(p) Search((p) + Width - 1, Width + 1)
-
- void CompressPi()
- {
- int Width2, i, Position;
- unsigned char *pp;
- int l0, l1, l2, l3, l4;
-
- if ( PiPlaneSize == 4 )
- WriteColor = PiWriteColor16;
- else
- WriteColor = PiWriteColor256;
- Width2 = Width * 2;
- for ( i = 0; i < Width2; i+=2 ) {
- Screen2[i] = Screen2[Width2];
- Screen2[i + 1] = Screen2[Width2 + 1];
- }
- pp = Screen2;
- RestLength = Width * Height / 2;
- WriteColor( 0, pp[Width2] );
- WriteColor( pp[Width2], pp[Width2 + 1] );
- Position = -1;
- do {
- l0 = l1 = l2 = l3 = l4 = 0;
- if ( Position != 0 )
- l0 = calc0(pp);
- if ( Position != 1 )
- l1 = calc1(pp);
- if ( Position != 2 )
- l2 = calc2(pp);
- if ( Position != 3 )
- l3 = calc3(pp);
- if ( Position != 4 )
- l4 = calc4(pp);
- if (!(l0 + l1 + l2 + l3 + l4)) {
- switch (Position) {
- case 0:
- PicBitWrite( 2, 0 );
- break;
- case 1:
- PicBitWrite( 2, 1 );
- break;
- case 2:
- PicBitWrite( 2, 2 );
- break;
- case 3:
- PicBitWrite( 3, 6 );
- break;
- case 4:
- PicBitWrite( 3, 7 );
- break;
- }
- for ( ;; ) {
- WriteColor( pp[Width2 - 1], pp[Width2 + 0] );
- WriteColor( pp[Width2 + 0], pp[Width2 + 1] );
- pp += 2;
- if ( !--RestLength )
- goto brk;
- l0 = calc0(pp);
- l1 = calc1(pp);
- l2 = calc2(pp);
- l3 = calc3(pp);
- l4 = calc4(pp);
- if ( l0 | l1 | l2 | l3 | l4 )
- break;
- PicBitWrite( 1, 1 );
- }
- PicBitWrite( 1, 0 );
- }
- Position = 0;
- if ( l0 < l1 ) {
- l0 = l1;
- Position = 1;
- }
- if ( l0 < l2 ) {
- l0 = l2;
- Position = 2;
- }
- if ( l0 < l3 ) {
- l0 = l3;
- Position = 3;
- }
- if ( l0 < l4 ) {
- l0 = l4;
- Position = 4;
- }
- switch (Position) {
- case 0:
- PicBitWrite( 2, 0 );
- break;
- case 1:
- PicBitWrite( 2, 1 );
- break;
- case 2:
- PicBitWrite( 2, 2 );
- break;
- case 3:
- PicBitWrite( 3, 6 );
- break;
- case 4:
- PicBitWrite( 3, 7 );
- break;
- }
- PiWriteLength (l0);
- RestLength -= l0;
- pp += l0 + l0;
- } while ( RestLength > 0 );
- brk:
- PicBitWrite( 32, 0 );
- }
-